tree grammar PascalTo3addrTree;

options {
tokenVocab=PascalTo3addr; // read token types from Expr.tokens file
ASTLabelType=CommonTree; // what is Java type of nodes?
}

@header {
import java.util.HashMap;
}

@members {
HashMap type = new HashMap();
}

module : ^('program' ID block); 

number 	: INT | FLOAT;

idList	:	ID
	|	ID idList;

block : declarations statementSequence ;

declarations
	: variableDeclBlock subprogDeclList 
	| variableDeclBlock;
	
variableDeclBlock 
	:	^('var' (variableDecl)*) ;

variableDecl : ^(type idList);

type : 'integer' | 'boolean' | 'real' | 'char' | arrayType ;
  
arrayType : ^('array' (subrange)+ type);

subrange 
	: ^('..' enumConstant enumConstant)
	| ^('..' CHAR CHAR) ;

enumConstant : ID | INT | 'true' | 'false' ;
constant : number | 'true' | 'false';

statementSequence : ^('XXX' statement (statement)* ;

statement : 	ifStatement
		| whileStatement 
		| repeatStatement
		| forStatement
		| iOStatement 
		| statementSequence 
		| 
		| 'break'
		| 'continue' 
		| assignment
		| functionCall 
		;
		
repeatStatement	: ^('repeat' statementSequence expression);

assignment : ^(':=' qualifiedName expression);
 
ifStatement 
	:	^('if' expression statement)
	|	^('if' expression statement statement);

whileStatement : ^('while' expression statement);

forStatement : ^('for' ID forRange statement);
forRange : ^(whichWay expression expression);
whichWay : 'to' | 'downto' ;

iOStatement 
	: ^('read' qualifiedList)  
	| ^('readln' qualifiedList) 
	| 'readln'
	| ^('write' expList)
	| ^('writeln' expList) 
	| 'writeln';

actualParameters : expList ;

expList : expression ( expression )* ;

expression 
	: simpleExpression
	| ^(relation simpleExpression simpleExpression);

simpleExpression 
	: term
	| unaryOperator term
	| ^(addOperator simpleExpression simpleExpression);
	
term	: factor
	| ^(multOperator factor factor)
	;

factor : 	constant
		| ^(ID actualParameters)
		| qualifiedName
		| expression 
		| 'not' factor ;

unaryOperator : ('+' | '-');
	
multOperator  : ('*' | '/' | 'div' | 'mod' | 'and');

addOperator  : ('+'| '-'| 'or'); 

relation : '=' | '<>' | '<' | '>' | '<=' | '>='	;
		
functionCall
	: ^(ID actualParameters)
	| ID;

subprogDeclList : (procedureDecl | functionDecl)* ;
 
procedureDecl : ^(procedureHeading block);

functionDecl : ^(functionHeading type block) ;

procedureHeading
	: ^('procedure' ID)
	| ^('procedure' ID formalParameters);

functionHeading
	: ^('function' ID)
	| ^('function' ID formalParameters);

formalParameters : oneFormalParam (oneFormalParam)*;

oneFormalParam : ('var' | 'const')? idList ':' type ;

qualifiedList : qualifiedName (qualifiedName)*;

qualifiedName 
	: ^(ID qualifiedStuff)
	| ID;

qualifiedStuff
	: (expList)+;
/*	
ID  :	('a'..'z'|'A'..'Z'|'_') ('a'..'z'|'A'..'Z'|'0'..'9'|'_')*
    ;

INT :	('0'..'9')+
    ;

FLOAT
    :   ('0'..'9')+ '.' ('0'..'9')* EXPONENT?
    |   '.' ('0'..'9')+ EXPONENT?
    |   ('0'..'9')+ EXPONENT
    ;

WS  :   ( ' '
        | '\t'
        | '\r'
        | '\n'
        ) {$channel=HIDDEN;}
    ;

CHAR:  '\'' ( ESC_SEQ | ~('\''|'\\') ) '\''
    ;

fragment
EXPONENT : ('e'|'E') ('+'|'-')? ('0'..'9')+ ;

fragment
HEX_DIGIT : ('0'..'9'|'a'..'f'|'A'..'F') ;

fragment
ESC_SEQ
    :   '\\' ('b'|'t'|'n'|'f'|'r'|'\"'|'\''|'\\')
    |   UNICODE_ESC
    |   OCTAL_ESC
    ;

fragment
OCTAL_ESC
    :   '\\' ('0'..'3') ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7') ('0'..'7')
    |   '\\' ('0'..'7')
    ;

fragment
UNICODE_ESC
    :   '\\' 'u' HEX_DIGIT HEX_DIGIT HEX_DIGIT HEX_DIGIT
    ;
*/